package com.qvtu.springboot.controller;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.unit.DataUnit;
import com.qvtu.springboot.Common.Result;
import com.qvtu.springboot.entity.Account;
import com.qvtu.springboot.entity.Admin;
import com.qvtu.springboot.entity.Employee;
import com.qvtu.springboot.exception.CustomException;
import com.qvtu.springboot.service.AdminService;
import com.qvtu.springboot.service.ArticleService;
import com.qvtu.springboot.service.EmployeeService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;


@RestController
public class WebController {
    @Resource
    private EmployeeService employeeService;

    @Resource
    private AdminService adminService;

    @Resource
    private ArticleService articleService;

    @GetMapping("/hello")
    public Result hello(){
        return Result.success("hello");
    }

    @PostMapping("/login")
    public Result login(@RequestBody Account account){
        Account result = null;
//        把确定的字符串放在这边 因为getRole可能出现null的情况，避免报错  （一般吧确定的字符串放在左边 不确定的字符串放在右边）
        if("Admin".equals(account.getRole())){
//            管理员
            result=adminService.login(account);
        }else if("Employee".equals(account.getRole())){
            result=employeeService.login(account);
        }else{
            throw new CustomException("500","非法输入");
        }
        return Result.success(result);
    }

    @PostMapping("/register")
    public Result register(@RequestBody Employee employee){
        employeeService.register(employee);
        return Result.success();
    }

    @PutMapping("/updatePassword")
    public Result updatePassword(@RequestBody Account account){
//        判断角色为管理员还是员工
        if("ADM".equals(account.getRole())){
            adminService.updatePassword(account);
        }else if("EMP".equals(account.getRole())){
            employeeService.updatePasswprd(account);
        }else{
            throw new CustomException("500","非法输入");
        }
        return Result.success();
    }

//    给前端的统计图提供接口
    @GetMapping("/barData")
    public Result getBarData(){
//        创建一个map对象 用于存储返回的数据 （map是一个键值对的数据结构 其中每一个键都唯一地映射一个值 它非常时候用来存储好检索结构化的数据 在这里map将部门名称和对应的员工数量组织在一起 方便前端使用）
        Map<String,Object> map=new HashMap<>();
//        获取所有的员工数据 这里null表示不带任何的筛选条件
        List<Employee> employeeList = employeeService.selectAll(null);
//        employeeList.stream()使用流操作 从员工列表中提取所有部门名称 并将其存储到一个Set中
//        Set是一个集合 不允许重复元素 因此可以确保部门名称的唯一性
//        .map(Employee::getDepartmentName) // 提取每个 Employee 对象的 departmentName 属性
//        collect(Collectors.toSet()将流中的元素收集到一个Set中 确保名称的唯一性)
        Set<String> departmentNameSet = employeeList.stream().map(Employee::getDepartmentName).collect(Collectors.toSet());
//        将部门名称集合存储到map中 键为department
        map.put("department",departmentNameSet);//x轴数据
        List<Long> countList=new ArrayList<>();
//        遍历每个部门的名称 使用流操作概率出该部门的员工 并统计数量
        for(String departmentName:departmentNameSet){
//            统计这个部门下的员工数量
            long count=employeeList.stream().filter(employee -> employee.getDepartmentName().equals(departmentName)).count();
            countList.add(count);
        }
        map.put("count",countList);//y轴员工数量的数据
        return Result.success(map);
    }

    @GetMapping("/lineData")
    public Result getLineData() {
        Map<String, Object> map = new HashMap<>();
//        Date是java中用于表示日期和事件的类 new Date() 调用构造器创建一个表示当前日期和时间的Date对象
        Date date = new Date(); // 今天当前的时间
//        DateTime是Date的一个子类 通常用于表示更加精准的日期时间的操作
//        offsetDate方法创建一个新的容器对象 方法接收两个参数 第一个参数表示原始日期 第二个参数表示要偏移的天数
//        这里表得到从当前日期开始往前推7天的日期
        DateTime start = DateUtil.offsetDay(date, -7); // 起始日期
//        rangeToList生成一个日期列表 列表从start日期开始 到date日期结束 按照指定频率（DateField.DAY_OF_YEAR表示每天）
        List<DateTime> dateTimeList = DateUtil.rangeToList(start, date, DateField.DAY_OF_YEAR);
//        .stream()将dateTimeList转换为流
//        .stream()将dateTimeList转换为流  DateUtil.format方法将每个日期格式化为MM月DD日的形式
        // 把 DateTime 类型的日期转换成 字符串类型的日期 ["10月22日", "10月23日"...]
//        map它的作用是对流中的每个元素执行一个函数，并产生一个新的流，其中包含了函数执行的结果。这使得你可以对集合中的元素进行转换或处理，而无需显式地编写循环代码。
        List<String> dateStrList = dateTimeList.stream().map(dateTime -> DateUtil.format(dateTime, "MM月dd日"))
//                .sorted(Comparator.naturlOrder())对流中的元素进行排序 Comparator.naturlOrder()表示按照自然顺序排序
                .sorted(Comparator.naturalOrder()).collect(Collectors.toList());
        map.put("date", dateStrList); // x轴数据
            List<Long> countList=new ArrayList<>();
        for (DateTime day : dateTimeList) {
            String dayFormat=DateUtil.formatDate(day);
            // 获取当天所有的发布的文章的数量
            long count = articleService.selectCountByDate(dayFormat);
            countList.add(count);
            map.put("count", countList); // Y轴上数量的数据
        }
        return Result.success(map);
    }

    @GetMapping("/pieData")
    public Result getPieDatd(){
//        创建饼图 每一个切片需要有name和value值 name表示切片的标签或类别名称 value代表该类别的数值 所以这里才使用ArrayList<>()存储切片元素数据
//        创建了一个ArrayList 每一个元素是一个map代表饼图的一个切片
        List<Map<String,Object>> list = new ArrayList<>();
        List<Employee> employeeList=employeeService.selectAll(null);
//        使用stream流处理employeeList（员工列表） 提取出每个员工的部门名称 在使用collect（Collectors.toSet()）将结果收集到一个Set中 使用Set可以自动去除重复的部门名称
//        当你使用map(Employee::getDepartmentName)时 你实际上是告诉流操作对每一个employee对象调用getDepartmentName方法 并返回结果
        Set<String> departmentNameSet=employeeList.stream().map(Employee::getDepartmentName).collect(Collectors.toSet());
        for(String departmentName:departmentNameSet){
            HashMap<String,Object> map=new HashMap<>();
            map.put("name",departmentName);
//            统计这个部门下面的员工数量
            long count=employeeList.stream().filter(employee -> employee.getDepartmentName().equals(departmentName)).count();
            map.put("value",count);
            list.add(map);
        }
        return Result.success(list);
    }



}
